package jdl.synchronization;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import jdl.databaseObjects.Database;
import jdl.databaseObjects.DbField;
import jdl.databaseObjects.DbType;
import jdl.databaseObjects.FieldCollection;
import jdl.databaseObjects.Table;
import jdl.databaseObjects.datatypes.sqlite.SqliteDbTypeFactory;

public class SqliteSynchronizer {
	private Connection connection;

	public SqliteSynchronizer(Connection connection) {
		this.connection = connection;
	}

	public void synchronizeDatabase(Database database) {

	}

	public void synchronizeField(DbField field) throws SynchronizationException {
		try {
			String tableName = field.getFieldCollection().getTable().getName();
			String sql = String.format("pragma table_info(%s)", tableName);
			PreparedStatement statement = connection.prepareStatement(sql);
			ResultSet resultSet = statement.executeQuery();
			while (resultSet.next()) {
				String name = resultSet.getString("name");
				if (name.compareToIgnoreCase(field.getName()) == 0) {
					String typeAsString = resultSet.getString("type");
					DbType type = SqliteDbTypeFactory.fromString(typeAsString);
					field.changeDbType(type);
					return;
				}
			}
		} catch (Exception e) {
			throw new SynchronizationException(e);
		}
		throw new DbObjectNotFoundException(field);
	}

	public void dispose() throws SQLException {
		connection.close();
	}

	public void synchronizeTable(Table table) throws SynchronizationException {
		if (!containsTable(table)) {
			throw new DbObjectNotFoundException();
		}
		table.toUnchanged();
		synchronizeFieldCollection(table.getFieldCollection());
	}

	public void synchronizeFieldCollection(FieldCollection fieldCollection)
			throws SynchronizationException {
		try {
			String tableName = fieldCollection.getTable().getName();
			String sql = String.format("pragma table_info(%s)", tableName);
			PreparedStatement statement = connection.prepareStatement(sql);
			ResultSet resultSet = statement.executeQuery();
			while (resultSet.next()) {
				String name = resultSet.getString("name");
				String typeAsString = resultSet.getString("type");
				DbType type = SqliteDbTypeFactory.fromString(typeAsString);
				DbField field = new DbField(name, type);
				fieldCollection.add(field);
			}
		} catch (Exception e) {
			throw new SynchronizationException(e);
		}
	}

	private boolean containsTable(Table table) throws SynchronizationException {
		try {
			PreparedStatement statement = connection
					.prepareStatement("SELECT name FROM sqlite_master WHERE name = ?;");
			statement.setString(1, table.getName());
			ResultSet resultSet = statement.executeQuery();
			return resultSet.next();
		} catch (SQLException e) {
			throw new SynchronizationException();
		}
	}
}
